﻿using System;
using ePipe;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Letter.IO;

#if NETSTANDARD2_1
using eLibrary.Extension;
#endif

namespace Letter.Net.Sockets;

abstract class ASocketRcver : SocketAwaitableEventArgs
{
    public ASocketRcver(PipeScheduler ioScheduler) : base(ioScheduler)
    {
    }

    protected ValueTask<SocketOperationResult> ReceiveAsync(Socket socket, Memory<byte> buffer)
    {
#if NETSTANDARD2_1
        ArraySegment<byte> segment = buffer.GetArray();
        SetBuffer(segment.Array, segment.Offset, segment.Count);
#elif NETCOREAPP
        SetBuffer(buffer);
#endif
        if (this.SocketRcvOperationAsync(socket))
        {
            return new ValueTask<SocketOperationResult>(this, 0);
        }

        var bytesTransferred = BytesTransferred;
        var error = SocketError;

        return error == SocketError.Success
            ? new ValueTask<SocketOperationResult>(new SocketOperationResult(bytesTransferred))
            : new ValueTask<SocketOperationResult>(new SocketOperationResult(CreateException(error)));
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    protected abstract bool SocketRcvOperationAsync(Socket socket);
}